Ссылка на презентацию: https://drive.google.com/file/d/1liD0-PT_8T1F8kyrbEURKk-I_sOgfyW0/view?usp=sharing
Давай работать над проектом в диалоге: если ты что-то меняешь в проекте или отвечаешь на мои комменатри — пиши об этом. Мне будет легче отследить изменения, если ты выделишь свои комментарии:
Всё это поможет выполнить повторную проверку твоего проекта оперативнее.
Вы решили открыть небольшое кафе в Москве. Оно оригинальное — гостей должны обслуживать роботы. Проект многообещающий, но дорогой. Вместе с партнёрами вы решились обратиться к инвесторам. Их интересует текущее положение дел на рынке — сможете ли вы снискать популярность на долгое время, когда все зеваки насмотрятся на роботов-официантов? Вы — гуру аналитики, и партнёры просят вас подготовить исследование рынка. У вас есть открытые данные о заведениях общественного питания в Москве.
Загрузите данные о заведениях общественного питания Москвы. Убедитесь, что тип данных в каждой колонке — правильный, а также отсутствуют пропущенные значения и дубликаты. При необходимости обработайте их.
Путь к файлу: /datasets/rest_data.csv.
Исследуйте соотношение видов объектов общественного питания по количеству. Постройте график.
Исследуйте соотношение сетевых и несетевых заведений по количеству. Постройте график.
Для какого вида объекта общественного питания характерно сетевое распространение?
Что характерно для сетевых заведений: много заведений с небольшим числом посадочных мест в каждом или мало заведений с большим количеством посадочных мест?
Для каждого вида объекта общественного питания опишите среднее количество посадочных мест. Какой вид предоставляет в среднем самое большое количество посадочных мест? Постройте графики.
Выделите в отдельный столбец информацию об улице из столбца address .
Постройте график топ-10 улиц по количеству объектов общественного питания. Воспользуйтесь внешней информацией и ответьте на вопрос — в каких районах Москвы находятся эти улицы?
Найдите число улиц с одним объектом общественного питания. Воспользуйтесь внешней информацией и ответьте на вопрос — в каких районах Москвы находятся эти улицы?
Сделайте общий вывод и дайте рекомендации о виде заведения, количестве посадочных мест, а также районе расположения. Прокомментируйте возможность развития сети.
Подготовьте презентацию исследования для инвесторов. Для создания презентации используйте любой удобный инструмент, но отправить презентацию нужно обязательно в формате pdf. Приложите ссылку на презентацию в markdown-ячейке в формате:
Презентация: <ссылка на облачное хранилище с презентацией>
Следуйте принципам оформления из темы «Подготовка презентации».
Оформление: Задание выполните в Jupyter Notebook. Программный код заполните в ячейках типа code, текстовые пояснения — в ячейках типа markdown. Примените форматирование и заголовки.
Таблица rest_data:
id — идентификатор объекта;
object_name — название объекта общественного питания;
chain — сетевой ресторан;
object_type — тип объекта общественного питания;
address — адрес;
number — количество посадочных мест.
#import scipy.stats as stats
import numpy as np
import pandas as pd
import seaborn as sns
from matplotlib import pyplot as plt
import plotly.express as px
from plotly import graph_objects as go
path = '/datasets/'
rest = pd.read_csv(path + 'rest_data.csv')
rest.sample(5, random_state = 12)
| id | object_name | chain | object_type | address | number | |
|---|---|---|---|---|---|---|
| 1498 | 21801 | Шантимель (кондитерские) | да | кафе | город Москва, Жулебинский бульвар, дом 5 | 32 |
| 14114 | 213535 | Шаверма | нет | предприятие быстрого обслуживания | город Москва, 1-й Силикатный проезд, дом 13 | 0 |
| 3807 | 26991 | Русская охота | нет | ресторан | город Москва, Смоленская улица, дом 5 | 100 |
| 8161 | 137704 | Бургер герой пивной бар | нет | бар | город Москва, улица Большая Ордынка, дом 19, с... | 76 |
| 12488 | 196637 | Столовая | нет | столовая | город Москва, 6-я Радиальная улица, дом 3, кор... | 24 |
rest.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 15366 entries, 0 to 15365 Data columns (total 6 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 id 15366 non-null int64 1 object_name 15366 non-null object 2 chain 15366 non-null object 3 object_type 15366 non-null object 4 address 15366 non-null object 5 number 15366 non-null int64 dtypes: int64(2), object(4) memory usage: 720.4+ KB
rest['object_name'].describe()
count 15366 unique 10393 top Столовая freq 267 Name: object_name, dtype: object
rest['object_name'].value_counts().head(15)
Столовая 267 Кафе 236 Шаурма 234 KFC 155 Шоколадница 142 Макдоналдс 122 Бургер Кинг 122 Домино'с Пицца 86 Теремок 84 Крошка Картошка 82 Пекарня 76 Милти 65 Суши Wok 61 Буфет 59 СТОЛОВАЯ 52 Name: object_name, dtype: int64
rest['object_name'] = rest['object_name'].str.lower()
rest['object_name'].value_counts()
столовая 321
кафе 278
шаурма 250
шоколадница 158
kfc 155
...
юнит 1
осьминожка 1
кухни кипра 1
столовая 16 при рудн 1
азербайджан 1
Name: object_name, Length: 9924, dtype: int64
rest['object_name'].nunique()
9924
rest['object_name'].value_counts().head(15)
столовая 321 кафе 278 шаурма 250 шоколадница 158 kfc 155 макдоналдс 151 бургер кинг 137 теремок 94 крошка картошка 90 домино'с пицца 90 буфет 82 пекарня 82 суши wok 72 милти 72 папа джонс 51 Name: object_name, dtype: int64
name_dict = {
'шоколадница':'шоколадница',
'kfc':'kfc',
'макдоналдс':'макдоналдс',
'бургер кинг':'бургер кинг',
'крошка картошка':'крошка картошка',
"домино'с пицца":"домино'с пицца",
'суши wok':'суши wok',
'папа джонс':'папа джонс',
'додо пицца':'додо пицца',
'якитория':'якитория',
'subway':'subway',
'сабвей':'subway',
'сабвэй':'subway',
'тануки':'тануки',
'starbucks':'starbucks',
'старбакс':'starbucks',
'лукойл':'лукойл',
'магбургер':'магбургер'
}
def replace_name(name):
for seach_name in name_dict:
if seach_name in name:
return name_dict[seach_name]
return name
rest['object_name'] = rest['object_name'].apply(replace_name)
rest['object_name'].value_counts().head(50)
столовая 321 кафе 278 шаурма 250 kfc 190 шоколадница 189 макдоналдс 173 бургер кинг 161 домино'с пицца 99 крошка картошка 96 теремок 94 буфет 82 пекарня 82 суши wok 76 милти 72 starbucks 69 папа джонс 68 subway 65 додо пицца 54 якитория 51 тануки 47 кофе с собой 46 школьно-базовая столовая 44 чайхона №1 43 донер кебаб 41 кафетерий 40 хинкальная 38 выпечка 36 кофе хаус 35 кофейня 33 хлеб насущный 32 прайм стар 26 иль патио 25 cofix 25 бистро 25 му-му 24 пиццерия 24 мята lounge 24 кулинария 23 бар 22 донер 20 андерсон 19 пицца хат 18 чайхона 16 кофе 16 комбинат питания мгту им.н.э.баумана 16 кулинарная лавка братьев караваевых 16 вьетнамская кухня 15 пицца паоло 15 столовая при гбоу школа 171 15 алло пицца 15 Name: object_name, dtype: int64
rest['object_name'].nunique()
9833
rest['chain'].value_counts()
нет 12398 да 2968 Name: chain, dtype: int64
rest['object_type'].value_counts()
кафе 6099 столовая 2587 ресторан 2285 предприятие быстрого обслуживания 1923 бар 856 буфет 585 кафетерий 398 закусочная 360 магазин (отдел кулинарии) 273 Name: object_type, dtype: int64
rest['number'].hist(figsize=(12,5), label='Посадочных мест от 0 до 25', bins=25, range=(0,25))
plt.xlabel('Кол-во посадочных мест, шт.')
plt.ylabel('Распределение - кол-во точек, шт.')
plt.title('Распределение посадочных мест от 0 до 25')
Text(0.5, 1.0, 'Распределение посадочных мест от 0 до 25')
rest = rest.drop(columns='id')
rest.duplicated().sum()
85
rest = rest.drop_duplicates()
rest
| object_name | chain | object_type | address | number | |
|---|---|---|---|---|---|
| 0 | сметана | нет | кафе | город Москва, улица Егора Абакумова, дом 9 | 48 |
| 1 | родник | нет | кафе | город Москва, улица Талалихина, дом 2/1, корпус 1 | 35 |
| 2 | кафе «академия» | нет | кафе | город Москва, Абельмановская улица, дом 6 | 95 |
| 3 | пиццетория | да | кафе | город Москва, Абрамцевская улица, дом 1 | 40 |
| 4 | кафе «вишневая метель» | нет | кафе | город Москва, Абрамцевская улица, дом 9, корпус 1 | 50 |
| ... | ... | ... | ... | ... | ... |
| 15361 | шоколадница | да | кафе | город Москва, 3-й Крутицкий переулок, дом 18 | 50 |
| 15362 | шоколадница | да | кафе | город Москва, улица Земляной Вал, дом 33 | 10 |
| 15363 | шоколадница | да | кафе | город Москва, улица Земляной Вал, дом 33 | 20 |
| 15364 | шоколадница | да | кафе | город Москва, поселение Московский, Киевское ш... | 36 |
| 15365 | шоколадница | да | кафе | город Москва, Ходынский бульвар, дом 4 | 10 |
15281 rows × 5 columns
fig = go.Figure(data=[go.Pie(labels=rest['object_type'].value_counts().index, values=rest['object_type'].value_counts(),
title='Соотношение видов объектов общественного питания по количеству')])
fig.show()
Как мы видим из диаграммы, наибольшее количество типов объектов составляют:
кафе 39,7%, столовые 16,9%, рестораны 14,9%, фастфуды 12,4% и бары 5,6%.
fig = go.Figure(data=[go.Pie(labels=rest['chain'].value_counts().index, values=rest['chain'].value_counts(), \
title='Соотношение сетевых и несетевых заведений по количеству')])
fig.show()
Как мы видим из круговой диаграммы - сетевых заведений лишь 19,4% от общего количества, остальные - несетевые
chain = rest.groupby(['object_type', 'chain'])['chain'].count()
chain.name = 'quantity'
chain = chain.reset_index()
chain
| object_type | chain | quantity | |
|---|---|---|---|
| 0 | бар | да | 37 |
| 1 | бар | нет | 818 |
| 2 | буфет | да | 11 |
| 3 | буфет | нет | 565 |
| 4 | закусочная | да | 56 |
| 5 | закусочная | нет | 292 |
| 6 | кафе | да | 1396 |
| 7 | кафе | нет | 4675 |
| 8 | кафетерий | да | 52 |
| 9 | кафетерий | нет | 343 |
| 10 | магазин (отдел кулинарии) | да | 78 |
| 11 | магазин (отдел кулинарии) | нет | 195 |
| 12 | предприятие быстрого обслуживания | да | 788 |
| 13 | предприятие быстрого обслуживания | нет | 1109 |
| 14 | ресторан | да | 543 |
| 15 | ресторан | нет | 1739 |
| 16 | столовая | да | 3 |
| 17 | столовая | нет | 2581 |
fig = px.bar(chain.sort_values(by='quantity'), x='object_type', y='quantity', color='chain', title='Объекты общественного питания',
labels=dict(quantity="Тип объекта", object_type="Кол-во объектов, шт."))
fig.show()
Как мы видим из диаграммы, наибольшее количество типов СЕТЕВЫХ объектов составляют:
кафе, Предприятие быстрого обслуживания, рестораны.
Среди остальных объектов намного меньше сетевых
chain_ratio = chain[chain['chain']=='да'].sort_values(by='quantity', ascending=False)
all_points = chain.groupby('object_type')['quantity'].sum().reset_index()
all_points.columns = ['object_type','total']
chain_ratio = chain_ratio.merge(all_points, on='object_type', how='left')
chain_ratio['part'] = (chain_ratio['quantity'] / chain_ratio['total']).round(3)
chain_ratio = chain_ratio.sort_values(by = 'part', ascending = False)
plt.figure(figsize=(12,5))
plt.bar(x=chain_ratio['object_type'], height=chain_ratio['part'])
plt.title('Доли сетевых объектов общественного питания для каждого типа')
plt.ylabel('Доля сетевых точек во всех для типа')
plt.xlabel('Тип объекта')
plt.xticks(rotation=45)
plt.show()
Как мы видим из графика, сетевое распространение характерно для предприятий быстрого обслуживания. В меньше мере оно характерно для магазинов, ресторанов и кафе.
plt.figure(figsize=(14,5))
plt.hist(rest[rest['chain']=='да']['number'],bins=50)
plt.title('Распределение кол-ва мест сразу по всем сетевым заведениям')
plt.grid()
plt.show()
rest_chains = rest[rest['chain']=='да']
rest_chains
| object_name | chain | object_type | address | number | |
|---|---|---|---|---|---|
| 3 | пиццетория | да | кафе | город Москва, Абрамцевская улица, дом 1 | 40 |
| 6 | брусника | да | кафе | город Москва, переулок Сивцев Вражек, дом 6/2 | 10 |
| 13 | алло пицца | да | кафе | город Москва, улица Авиаторов, дом 14 | 32 |
| 16 | суши wok | да | предприятие быстрого обслуживания | город Москва, Азовская улица, дом 3 | 7 |
| 18 | тануки | да | ресторан | город Москва, Большая Академическая улица, дом 65 | 160 |
| ... | ... | ... | ... | ... | ... |
| 15361 | шоколадница | да | кафе | город Москва, 3-й Крутицкий переулок, дом 18 | 50 |
| 15362 | шоколадница | да | кафе | город Москва, улица Земляной Вал, дом 33 | 10 |
| 15363 | шоколадница | да | кафе | город Москва, улица Земляной Вал, дом 33 | 20 |
| 15364 | шоколадница | да | кафе | город Москва, поселение Московский, Киевское ш... | 36 |
| 15365 | шоколадница | да | кафе | город Москва, Ходынский бульвар, дом 4 | 10 |
2964 rows × 5 columns
rest_chains.groupby('object_name')['object_name'].count().sort_values(ascending = False).head()
object_name kfc 188 шоколадница 185 макдоналдс 172 бургер кинг 159 домино'с пицца 99 Name: object_name, dtype: int64
plt.figure(figsize=(14,5))
plt.hist(rest[rest['chain']=='да']['number'],bins=10, range=(0,10))
plt.title('Распределение кол-ва мест сразу по всем сетевым заведениям')
plt.grid()
plt.show()
По графику видно, что есть много "сетевых" объектов, у которых всего 1 точка.
chain_sit_quant = rest_chains.groupby('object_name').agg({'chain':'count' ,'number':'median'}).reset_index()
chain_sit_quant
| object_name | chain | number | |
|---|---|---|---|
| 0 | beverly hills diner | 1 | 88.0 |
| 1 | bierloga | 1 | 75.0 |
| 2 | black & white | 1 | 40.0 |
| 3 | bocconcino | 3 | 68.0 |
| 4 | boobo | 1 | 46.0 |
| ... | ... | ... | ... |
| 488 | ямми микс | 1 | 2.0 |
| 489 | ян примус | 1 | 300.0 |
| 490 | японский ресторан «ваби-саби» | 1 | 155.0 |
| 491 | япоша | 2 | 105.0 |
| 492 | ёрш | 4 | 104.0 |
493 rows × 3 columns
ax = sns.jointplot(x="chain", y="number", data=chain_sit_quant, height = 8, xlim=(0,15), ylim=(0,100), kind= 'kde', fill = True,
joint_kws={'alpha': 0.5},)
plt.yticks([0,10,20,30,40,50,60,70,80,90,100])
plt.title('Посадочные места и их кол-во в сетевых заведениях' , fontsize=14)
ax.set_axis_labels('Кол-во зеведений', 'Кол-во посадочных мест', fontsize=14)
plt.show()
Вывод:
для сетевых объектов характерно кол-во заведений от 0 и до 6;
количество посадочных мест - от 10 до 50
chain_objects = rest[rest['chain']=='да'].groupby('object_name').agg({'object_name':'count', 'number':'mean'})
chain_objects.columns = ['objects', 'mean_number']
plt.figure(figsize=(10,5))
plt.scatter(chain_objects['mean_number'], chain_objects['objects'], alpha = 0.4)
plt.xlabel('Среднее кол-во посадочных мест')
plt.ylabel('Кол-во точек в сети')
plt.title('Распределение количества сетевых заведений \n и их среднее количество посадочных мест', fontsize=13)
plt.axhline(np.percentile(chain_objects['objects'], 95), linestyle='--', color='black')
plt.axvline(np.percentile(chain_objects['mean_number'], 95), linestyle='--', color='black')
plt.plot(chain_objects['mean_number'].mean(), chain_objects['objects'].mean(), marker='.', ls='none', ms=10, color = 'red' )
plt.text(330,20, '95% заведений ниже этой линии')
plt.text(175,90, '95% заведений левее этой линии')
plt.show()
print(chain_objects['mean_number'].mean(), chain_objects['objects'].mean())
60.981272655982416 6.012170385395538
По графику видно, что в 95% количество точек сети не превышает 21, количество посадочных мест - не более 172
number_of_seats_by_object = rest.pivot_table(index='object_type', values='number', aggfunc='mean').sort_values(by='number', ascending=False).reset_index()
number_of_seats_by_object.columns=['object_type', 'avg_seats']
number_of_seats_by_object['avg_seats'] = number_of_seats_by_object['avg_seats'].round(2)
print(number_of_seats_by_object)
my_order1 = rest.groupby(by=["object_type"])["number"].mean().sort_values().iloc[::-1].index
plt.figure(figsize=(15,8))
ax = sns.boxplot(x='object_type', y='number', data = rest, showmeans=True, order = my_order1)
plt.ylim(0, 500)
plt.xlabel('Тип объекта')
plt.ylabel('Кол-во посадочных мест')
plt.title('Кол-во посадочных мест по видам объектов')
plt.setp(ax.get_xticklabels(), rotation=45)
plt.show()
object_type avg_seats 0 столовая 130.34 1 ресторан 96.88 2 буфет 51.43 3 бар 43.53 4 кафе 39.79 5 предприятие быстрого обслуживания 20.81 6 кафетерий 9.18 7 закусочная 7.85 8 магазин (отдел кулинарии) 5.59
Как мы видим из графика, именно у объектов типа СТОЛОВАЯ наибольшее количество посадочных мест - в среднем 130
На втором месте идет ресторан с 97 местами
address = rest['address'].to_list()
streets = []
for street in address:
start = street.find('город москва')
if "владение" in street:
end = street.find('владение')
streets.append(street[start+15:end-2])
else:
end = street.find('дом')
streets.append(street[start+15:end-2])
rest['street_name'] = streets
rest.sample(10, random_state = 3)
| object_name | chain | object_type | address | number | street_name | |
|---|---|---|---|---|---|---|
| 6869 | бургер кинг | да | предприятие быстрого обслуживания | город Москва, Строгинский бульвар, дом 1 | 55 | Строгинский бульвар |
| 14072 | мск кальянная | нет | кафе | город Москва, Солнцевский проспект, дом 21 | 40 | Солнцевский проспект |
| 11898 | subway | да | кафе | город Москва, улица Лобачевского, дом 112А, ст... | 10 | улица Лобачевского |
| 6639 | пекинская утка | нет | ресторан | город Москва, Рублёвское шоссе, дом 62 | 70 | Рублёвское шоссе |
| 2131 | столовая «колледж 32» | нет | столовая | город Москва, улица Орджоникидзе, дом 15 | 20 | улица Орджоникидзе |
| 14944 | krispy kreme | нет | кафе | город Москва, Ходынский бульвар, дом 4 | 0 | Ходынский бульвар |
| 14547 | суши маркет | нет | кафе | город Москва, улица Орджоникидзе, дом 11 | 40 | улица Орджоникидзе |
| 14028 | kislovsky | нет | ресторан | город Москва, Большой Кисловский переулок, дом... | 98 | Большой Кисловский переулок |
| 10911 | столовая при школе № 647 | нет | столовая | город Москва, 5-я улица Соколиной Горы, дом 14 | 80 | 5-я улица Соколиной Горы |
| 10614 | ресторан воробьевы горы | нет | ресторан | город Москва, Мичуринский проспект, дом 6, кор... | 80 | Мичуринский проспект |
top_streets = rest.groupby('street_name', as_index=False).agg({'object_name':'count'})
top_streets.columns = ['street', 'objects']
top_streets = top_streets.sort_values(by='objects', ascending = False)
top10_streets = top_streets.head(10)
print('Топ-10 улиц с наибольшим количеством заведений:\n', top10_streets)
fig = px.bar(top10_streets, x='street', y='objects',
color='street', width = 900, height = 550, text='objects')
fig.update_xaxes(tickangle=45)
fig.update_layout(
title='Топ-10 улиц с наибольшим количеством заведений',
xaxis_title="Улица",
yaxis_title="Количество заведений")
fig.show()
Топ-10 улиц с наибольшим количеством заведений:
street objects
1647 проспект Мира 203
1005 Профсоюзная улица 181
691 Ленинградский проспект 170
991 Пресненская набережная 167
412 Варшавское шоссе 161
694 Ленинский проспект 147
1644 проспект Вернадского 128
682 Кутузовский проспект 114
608 Каширское шоссе 111
613 Кировоградская улица 108
streets_with_1_object = top_streets[top_streets['objects']==1]
print('Всего улиц с 1 объектом общественного питания: {}, что составляет {:.1%} от всего кол-ва улиц с объектами общественного питания'\
.format(len(streets_with_1_object), (len(streets_with_1_object)/len(top_streets))))
Всего улиц с 1 объектом общественного питания: 678, что составляет 32.1% от всего кол-ва улиц с объектами общественного питания
rest.to_csv(r"C:\Users\227650\Downloads\rest1.csv", index=False)